/**
 * @file resnet50Lib.cpp
 * @author hongjian.huang (hongjian.huang@lynxi.com)
 * @brief
 * @version 0.1
 * @date 2022-08-26
 *
 * Copyright:
 * © 2018 北京灵汐科技有限公司 版权所有。
 * 注意：以下内容均为北京灵汐科技有限公司原创，未经本公司允许，不得转载，否则将视为侵权；对于不遵守此声明或者其他违法使用以下内容者，本公司依法保留追究权。
 * © 2018 Lynxi Technologies Co., Ltd. All rights reserved.
 * NOTICE: All information contained here is, and remains the property of Lynxi.
 * This file can not be copied or distributed without the permission of Lynxi
 * Technologies Co., Ltd.
 *
 * @par 修改日志:
 * Data:2022-08-26
 * Author: hongjian.huang
 * Description:
 */

#include "resnet50Lib.h"
#include "resnet50Label.h"
#include <algorithm>
#include <cmath>
#include <iomanip>
#include <iostream>
#include <sys/time.h>
#ifdef LYNXI_PLUGIN
#include "lyn_plugin_dev.h"
#endif
#include "drawTool.h"
#include <codecvt>
#include <string>
#include <utility>
const int sig[2] = {1, -1};
const float result = 5.96046e-08;

float half2float(int16_t ib) {
  int16_t s, e, m;
  s = (ib >> 15) & 0x1;
  e = (ib >> 10) & 0x1f;
  m = ib & 0x3ff;

  {
    if (0 == e)
      return sig[s] * m * result;
    else {
      union {
        unsigned int u32;
        float f32;
      } ou;

      e = (0x1f == e) ? 0xff : (e - 15 + 127);
      ou.u32 = (s << 31) | (e << 23) | (m << 13);
      return ou.f32;
    }
  }
}

inline std::wstring
to_wide_string(const std::string &input) // string to wstring
{
  std::wstring_convert<std::codecvt_utf8<wchar_t>> converter;
  return converter.from_bytes(input);
}

int LynResNet50Process(ResNetPostInfo *para) {
  uint16_t *ptr = nullptr;
  unsigned char *imgData = nullptr;
#ifdef LYNXI_PLUGIN
  ptr = (uint16_t *)lynPluginGetVirtAddr(para->apuOut);
  imgData = (unsigned char *)lynPluginGetVirtAddr(para->imgData);
#else
  ptr = (uint16_t *)para->apuOut;
  imgData = (unsigned char *)para->imgData;
#endif

  int iStep = sizeof(float) / 2;
  int iCount = para->apuOutSize / iStep;
  if (para->apuOutSize % iStep != 0) {
    // LOG_PLUGIN_E("data is not match");
    return -1;
  }

  std::pair<int, float> pairResult(0, 0.0);
  for (int i = 0; i < iCount; i++) {
    float fTmp = half2float(*((int16_t *)ptr + i));
    // float fTmp = *((float*)pHostData + i);
    if (fTmp > pairResult.second) {
      pairResult.first = i;
      pairResult.second = fTmp;
    }
  }

  if (pairResult.first < 0 || pairResult.first >= arrLabelSize) {
    // LOG_PLUGIN_E("ERROR!!! idCategory : %d is out of range!!!\n",
    //              pairResult.first);
    return -1;
  }

  std::string res = resnet_label[pairResult.first];
  std::wstring ws_res = to_wide_string(res);
  DrawTextAttrV2 textAttr;
  textAttr.imgData = imgData;
  textAttr.imgH = para->imgDataH;
  textAttr.imgW = para->imgDataW;
  textAttr.imgFmt = para->imgFmt;
  textAttr.fontSize = SAMPLE_FONT_SIZE_128;
  textAttr.startX = 20;
  textAttr.startY = 100;
  textAttr.color = SAMPLE_DRAW_COLOR_RED;
  textAttr.text = const_cast<wchar_t *>(ws_res.c_str());
  PluginDrawTextV2(&textAttr);
  return 0;
};
